#define WINDOW_X_DIM		800
#define WINDOW_Y_DIM		800
#define FRAME_TIME			30
#define V_FIELD_OF_VIEW		60


// this is delineating the arena!
#define ARENA_WIDTH			21
#define ARENA_HEIGHT		20

#include "Includes.h"

Window window;
Camera camera;
World world( 10, 10 );
InputWrapper input;


// advance declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void processInput();


// ENTRY POINT
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, char * cmdParam, int cmdShow) {


	// misc startup chores
//	createConsole();
	srand( time(NULL) );



	// prep the big players
	window.setup(WindowProcedure, hInst, "wndclass", WINDOW_X_DIM, WINDOW_Y_DIM);
	camera.setup(V_FIELD_OF_VIEW, (float)window.width/(float)window.height, 0.5, 10000);
	input.setup(window.handle);


	// some simple OpenGL initialization
	glDepthFunc		(GL_LEQUAL);
	glEnable		(GL_DEPTH_TEST);
	glEnable		(GL_CULL_FACE);
	glPolygonOffset (1.0, 1.5);

	

	//because I want it to be here for now!
	camera.position  = Vertex(ARENA_WIDTH/2, ARENA_HEIGHT/2, 24);
	world.player.position = Vertex(ARENA_WIDTH/2, ARENA_HEIGHT/2, 0);


	// these'll help me tick, and also with the framerate
	long lastFrame, now, elapsed;
	lastFrame = timeGetTime();


	// get on with the message loop
	MSG  msg ;

	while (true) {
		// clear the message queue before moving into the bottom of the loop (it's only polite)
		while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) {

			// this is the only way out of the while(true) loop
			if ( msg.message == WM_QUIT ) {
				window.shutDown();
				input.shutDown();
				return msg.wParam;
			}

			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}



		// choke the framerate
		now = timeGetTime();
		elapsed = now - lastFrame;
		if (now-lastFrame < FRAME_TIME)
			Sleep( FRAME_TIME - elapsed );
		lastFrame = now;


		// if the window isn't on top, cut back up to minimize CPU hit
		if (window.handle != GetActiveWindow()) 
			continue;
		


		// deal with input
		input.update();
		processInput();


		// tick the world
		world.tick( elapsed );



		// then, draw a frame
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		camera.prepTransformations();


		world.draw();

		SwapBuffers(window.deviceContext);
    }

}
//





void processInput() {

	// these statics are used to control the input mode
	enum inputModes { KEYBOARD, GAMEPAD };
	static inputModes inputMode = input.gamepad.exists ? GAMEPAD : KEYBOARD;
	static bool inputSwitchReleased = true;


	// quit abruptly if ESC is pressed
	if (input.keyboard.state[ DIK_ESCAPE ] & 0x80)
		PostQuitMessage(0);


	// if F1 is pressed, switch between input modes
	if ((input.keyboard.state[ DIK_F1 ] & 0x80) && inputSwitchReleased) {
		if (inputMode == KEYBOARD)	inputMode = GAMEPAD;
		else						inputMode = KEYBOARD;
		inputSwitchReleased = false;
	}
	else if (!((input.keyboard.state[ DIK_F1 ] & 0x80) || inputSwitchReleased)) {
		inputSwitchReleased = true;
	}


	// basic movement, until I get something more sophisticated in place (yeah, like THAT's gonna happen)
	// REALLY GOTTA GET SOME TICK-BASED MOVEMENT IN HERE!!!!
	if (inputMode == KEYBOARD) {
		if (input.keyboard.state[ DIK_W ] & 0x80)		world.player.translate(  0,  1, 0 );
		if (input.keyboard.state[ DIK_S ] & 0x80)		world.player.translate(  0, -1, 0 );
		if (input.keyboard.state[ DIK_A ] & 0x80)		world.player.translate( -1,  0, 0 );
		if (input.keyboard.state[ DIK_D ] & 0x80)		world.player.translate(  1,  0, 0 );


		// and here's for the shooting!
		bool up, down, left, right;
		up		= input.keyboard.state[ DIK_UP ]	& 0x80;
		down	= input.keyboard.state[ DIK_DOWN ]	& 0x80; 
		left	= input.keyboard.state[ DIK_LEFT ]	& 0x80;
		right	= input.keyboard.state[ DIK_RIGHT ] & 0x80;

		if		(  up && !right && !down && !left )	world.nextBulletVelocity = Vector( 0, 1, 0);
		else if (  up &&  right && !down && !left )	world.nextBulletVelocity = Vector( 1, 1, 0);
		else if ( !up &&  right && !down && !left )	world.nextBulletVelocity = Vector( 1, 0, 0);
		else if ( !up &&  right &&  down && !left )	world.nextBulletVelocity = Vector( 1,-1, 0);
		else if ( !up && !right &&  down && !left )	world.nextBulletVelocity = Vector( 0,-1, 0);
		else if ( !up && !right &&  down &&  left )	world.nextBulletVelocity = Vector(-1,-1, 0);
		else if ( !up && !right && !down &&  left )	world.nextBulletVelocity = Vector(-1, 0, 0);
		else if (  up && !right && !down &&  left )	world.nextBulletVelocity = Vector(-1, 1, 0);
	}
	
	else if (inputMode == GAMEPAD) {
		float lx = 2 * (float)(input.gamepad.state.lx - 32767) / 65535;
		float ly = -2 * (float)(input.gamepad.state.ly - 32767) / 65535;
		world.player.translate( lx, ly, 0 );

		float rx = 2 * (float)(input.gamepad.state.rx - 32767) / 65535;
		float ry = -2 * (float)(input.gamepad.state.ry - 32767) / 65535;

		if (rx != 0 || ry != 0)
			world.nextBulletVelocity = Vector(rx, ry, 0);	
		
	}

}
//







LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	
	if  (message == WM_SIZE) {
		window.resize( LOWORD(lParam), HIWORD(lParam));
		camera.setup(V_FIELD_OF_VIEW, (float)window.width/(float)window.height, 0.5, 10000);
		return 0;
	};

	if (message == WM_DESTROY) { 
		PostQuitMessage(0); 
		return 0; 
	}

	return ::DefWindowProc (hwnd, message, wParam, lParam );
}
//

